import { defineComponent, ref, watch, computed, watchEffect, createVNode, Teleport, createApp, mergeProps, isVNode } from 'vue';
import usePortal from '../use/usePortal.js';
import usezIndex from '../use/usezIndex.js';
import { createUniqueId } from '../use/createUniqueId.js';
import Draggable from '../Draggable/index.js';
import Button from '../Button/index.js';
import { FeatherX } from 'cui-vue-icons/feather';
import { F7InfoCircleFill, F7CheckmarkAltCircleFill, F7ExclamationmarkTriangleFill, F7XmarkCircleFill, F7QuestionCircleFill } from 'cui-vue-icons/f7';
import useTransition from '../use/useTransition.js';

function _isSlot(s) {
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
}
const icons = {
  info: F7InfoCircleFill,
  success: F7CheckmarkAltCircleFill,
  warning: F7ExclamationmarkTriangleFill,
  error: F7XmarkCircleFill,
  confirm: F7QuestionCircleFill
};
const Modal = /* @__PURE__ */ defineComponent({
  name: 'Modal',
  props: {
    bounds: {
      type: String
    },
    disabled: {
      type: Boolean
    },
    style: {
      type: Object
    },
    class: {
      type: String
    },
    headerStyle: {
      type: Object
    },
    bodyStyle: {
      type: Object
    },
    title: {
      type: [String, Object]
    },
    content: {
      type: [String, Object]
    },
    footer: {
      type: Boolean,
      default: true
    },
    footerAlign: {
      type: String
    },
    footerReverse: {
      type: Boolean
    },
    loading: {
      type: Boolean
    },
    okText: {
      type: [String, Function]
    },
    okButtonType: {
      type: String
    },
    cancleButtonType: {
      type: String
    },
    cancleText: {
      type: [String, Function]
    },
    defaultPosition: {
      type: Object
    },
    mask: {
      type: Boolean,
      default: true
    },
    maskClosable: {
      type: Boolean,
      default: true
    },
    resetPostion: {
      type: Boolean,
      default: false
    },
    hasCloseIcon: {
      type: Boolean
    },
    fullScreen: {
      type: Boolean
    },
    modelValue: {
      type: Boolean
    },
    destroyOnClose: {
      type: Boolean
    },
    onOk: {
      type: Function
    },
    onCancel: {
      type: Function
    }
  },
  emits: ['update:modelValue', 'closed', 'clickClose'],
  setup(props, {
    emit,
    slots
  }) {
    const wrap = ref();
    let maskEle;
    let draggable;
    const visible = ref(props.modelValue);
    const loading = ref(false);
    const opened = ref(visible.value);
    const destroyed = ref(props.destroyOnClose && !opened.value);
    let setOverflow = false;
    let originOverflow = '';
    const footerAlign = props.footerAlign ?? 'end';
    const footerReverse = props.footerReverse ?? false;
    const okButtonType = props.okButtonType ?? 'primary';
    const cancleButtonType = props.cancleButtonType ?? 'default';
    const zindex = usezIndex();
    const id = 'cm-modal-portal';
    const footer = props.footer ?? true;
    const modalId = createUniqueId();
    const okText = props.okText || '确 定';
    const cancleText = props.cancleText || '取 消';
    const mask = props.mask ?? true;
    const maskClosable = props.maskClosable ?? true;
    const hasCloseIcon = props.hasCloseIcon ?? true;
    props.resetPostion ?? false;
    watch(() => props.modelValue, val => {
      visible.value = val;
    });
    watch(visible, val => {
      emit('update:modelValue', val);
    });
    const wrapClass = computed(() => ({
      'cm-modal-wrap': true,
      'cm-modal-fullscreen': props.fullScreen
    }));
    const maskClass = computed(() => ({
      'cm-modal-mask': true,
      'cm-modal-mask-visible': visible.value
    }));
    const onClickClose = () => {
      emit('clickClose');
      onClose();
    };
    const onClose = () => {
      emit('closed');
      visible.value = false;
    };
    const onCancel = () => {
      onClose();
      props.onCancel?.();
    };
    const onOk = async () => {
      // 先判断显示loading
      if (props.loading) {
        if (!loading.value) {
          loading.value = true;
        }
      }
      // 如果存在onOK回调判断是否返回值
      if (props.onOk) {
        const ret = await props.onOk?.();
        // 没有返回值并且非loading直接关闭
        if (ret === undefined && !loading.value) {
          onClose();
        }
        // 返回true直接关闭
        if (ret === true) {
          onClose();
        }
        // 返回false，重置loading
        if (ret === false) {
          loading.value = false;
        }
      } else {
        if (!loading.value) {
          onClose();
        }
      }
    };
    watchEffect(() => {
      const show = opened.value;
      const resetPostion = props.resetPostion;
      if (!show) {
        loading.value = false;
        if (setOverflow) {
          document.body.style.overflow = originOverflow;
          setOverflow = false;
        }
      } else {
        if (wrap.value) {
          const wrapH = wrap.value.getBoundingClientRect().height;
          const contentH = wrap.value.children[0].getBoundingClientRect().height;
          // 超出显示内容
          if (contentH > wrapH) {
            wrap.value.style.overflow = 'auto';
            wrap.value.children[0].style.top = 0;
            const bodyStyle = window.getComputedStyle(document.body, null);
            originOverflow = bodyStyle.overflow;
            if (originOverflow !== 'hidden') {
              document.body.style.overflow = 'hidden';
              setOverflow = true;
            }
          } else {
            wrap.value.style.overflow = 'none';
            setOverflow = false;
          }
          setTimeout(() => {
            wrap.value.focus();
          }, 300);
        }
        if (resetPostion) {
          if (draggable) {
            draggable.reset();
          }
        }
      }
    });
    const transition = useTransition({
      el: () => wrap.value,
      startClass: 'cm-modal-visible',
      activeClass: 'cm-modal-open',
      enterEndClass: 'cm-modal-opened',
      onLeave: () => {
        opened.value = false;
        props.destroyOnClose && (destroyed.value = true);
      },
      onEnter: () => {
        opened.value = true;
      }
    });
    watchEffect(() => {
      const v = visible.value;
      if (v) {
        props.destroyOnClose && (destroyed.value = false);
        transition.enter();
      } else {
        transition.leave();
      }
    });
    const onMaskClick = e => {
      if (maskClosable) {
        if (e.target === maskEle) {
          visible.value = false;
        }
      }
    };
    const onkeydown = e => {
      if (e.keyCode === 27) {
        visible.value = false;
      }
    };
    return () => createVNode(Teleport, {
      "to": usePortal(id, id)
    }, {
      default: () => [mask ? createVNode("div", {
        "class": maskClass.value,
        "onClick": onMaskClick,
        "ref": el => maskEle = el,
        "style": {
          "z-index": zindex - 1
        }
      }, null) : null, createVNode("div", {
        "class": wrapClass.value,
        "ref": wrap,
        "tab-index": "1",
        "onKeydown": onkeydown,
        "style": {
          "z-index": zindex
        }
      }, [createVNode(Draggable, {
        "ref": el => draggable = el,
        "bounds": props.bounds || 'body',
        "style": props.defaultPosition,
        "handle": '.cm-modal-header[data-id="' + modalId + '"]',
        "disabled": props.disabled
      }, {
        default: () => [createVNode("div", {
          "class": "cm-modal",
          "style": props.style
        }, [createVNode("div", {
          "class": "cm-modal-header",
          "style": props.headerStyle,
          "data-id": `${modalId}`
        }, [props.title ? createVNode("div", {
          "class": "cm-modal-title"
        }, [props.title]) : null, hasCloseIcon ? createVNode("span", {
          "class": "cm-modal-close",
          "onClick": onClickClose
        }, [createVNode(FeatherX, null, null)]) : null]), createVNode("div", {
          "class": "cm-modal-body",
          "style": props.bodyStyle
        }, [destroyed.value ? null : slots.default?.()]), footer ? createVNode("div", {
          "class": {
            'cm-modal-footer': true,
            'cm-modal-footer-reverse': footerReverse,
            [`cm-modal-footer-${footerAlign}`]: !!footerAlign
          }
        }, [createVNode(Button, {
          "type": okButtonType,
          "loading": loading.value,
          "onClick": onOk
        }, _isSlot(okText) ? okText : {
          default: () => [okText]
        }), createVNode(Button, {
          "type": cancleButtonType,
          "onClick": onCancel
        }, _isSlot(cancleText) ? cancleText : {
          default: () => [cancleText]
        })]) : null])]
      })])]
    });
  }
});
function ModalFun() {
  const visible = ref(true);
  let app;
  return {
    open(config) {
      visible.value = true;
      const status = config.status;
      const icon = () => icons[status] ? createVNode(icons[status], {
        class: `cm-modal-icon-${status}`,
        size: 24
      }) : null;
      const close = v => {
        visible.value = false;
        setTimeout(() => {
          app.unmount();
          app = null;
        }, 250);
      };
      config.style = {
        'min-width': '24vw',
        ...config.style
      };
      config.defaultPosition = {
        top: '200px',
        ...config.defaultPosition
      };
      delete config.status;
      const ele = usePortal('cm-modal-portal-instance', 'cm-modal-portal');
      if (!app) {
        app = createApp(() => createVNode(Modal, mergeProps(config, {
          "onClosed": close,
          "modelValue": visible.value,
          "onUpdate:modelValue": $event => visible.value = $event,
          "class": "cm-modal-instance"
        }), {
          default: () => [icons[status] ? createVNode("div", {
            "class": "cm-modal-left"
          }, [createVNode("div", {
            "class": "cm-modal-icon"
          }, [icon()])]) : null, createVNode("div", {
            "class": "cm-modal-right"
          }, [typeof config.content === 'function' ? config.content() : config.content])]
        }));
        app.mount(ele);
      } else {
        app.unmount();
      }
    },
    success(config) {
      config.status = 'success';
      return this.open(config);
    },
    info(config) {
      config.status = 'info';
      return this.open(config);
    },
    warning(config) {
      config.status = 'warning';
      return this.open(config);
    },
    error(config) {
      config.status = 'error';
      return this.open(config);
    },
    confirm(config) {
      config.status = 'confirm';
      return this.open(config);
    },
    remove() {
      visible.value = false;
      setTimeout(() => {
        if (app) {
          app.unmount();
        }
      }, 250);
    }
  };
}
const modal = ModalFun();

export { Modal as default, modal };
